
import 'package:flutter/material.dart';
import 'package:FlutterReader/router/context_extension.dart';

import '../../wights/switcher.dart';
import '../../wights/clickable.dart';

class GroupSetting extends StatelessWidget {
  // 收集所有子项
  final List<Item> children;

  final double vSpacing;
  final double hSpacing;
  final EdgeInsets boxInsets;

  GroupSetting({
    super.key,
    required this.children, this.vSpacing = 8, this.hSpacing = 8
  }) : boxInsets = EdgeInsets.symmetric(vertical: vSpacing, horizontal: hSpacing);

  @override
  Widget build(BuildContext context) {
    // SizedBox.expand：撑满容器的一种方式
    return SizedBox.expand(
      // 单子组件滚动视图
      child: SingleChildScrollView(
        // BouncingScrollPhysics：具有回弹效果的设置项
        physics: const AlwaysScrollableScrollPhysics(
          parent: BouncingScrollPhysics(),
        ),

        // 用 ListView 来呈现所有的子项
        child: ListView.builder(
          shrinkWrap: true,
          // 去除重复边界

          addRepaintBoundaries: false,
          // 禁用 ListView 的滚动效果
          // 这样一来子项无论有多少，都会直接显示出来
          // 然后由外部的 SingleChildScrollView 负责滚动
          physics: const NeverScrollableScrollPhysics(),

          // ListView 子组件的生成数量
          // 如果不设置的话，滚动时会无限生成子项
          itemCount: children.length,

          // 动态创建子项内容，通过 Item 抽象类来决定具体的内容
          itemBuilder: (context, index) {
            Item item = children[index];
            Widget widget = item.build(this, context);
            return widget;
          },
        ),
      ),
    );
  }
}

abstract class Item {
  // 静态方法访问内部类
  static Item customize(Widget child) => _ItemCustomize(child);
  static Item spacer([double space = 10]) => _ItemSpacer(space);
  static Item leading(String text) => _ItemLeading(text);
  static Item text({
    Widget? icon,
    required String title,
    String? subtitle,
    String? description,
    VoidCallback? onTap,
    Type? goto,
  }) =>
      _ItemText(
        title: title,
        subtitle: subtitle,
        icon: icon,
        description: description,
        onTap: onTap,
        goto: goto,
      );
  static Item switcher({
    Widget? icon,
    required String title,
    String? subtitle,
    String? description,
    bool value = false,
    OnChanged? onChanged,
  }) =>
      _ItemSwitcher(
        title: title,
        subtitle: subtitle,
        icon: icon,
        description: description,
        value: value,
        onChanged: onChanged,
      );
  static Item notification({
    Widget? icon,
    required String title,
    String? subtitle,
    String? description,
    VoidCallback? onTap,
    Type? goto,
  }) =>
      _ItemNotification(
        title: title,
        subtitle: subtitle,
        icon: icon,
        description: description,
        onTap: onTap,
        goto: goto,
      );

  Widget build(GroupSetting widget, BuildContext context);
}


class _ItemCustomize extends Item {
  final Widget child;

  _ItemCustomize(this.child);

  @override
  Widget build(GroupSetting widget, BuildContext context) => child;
}

class _ItemSpacer extends Item {
  final double space;

  _ItemSpacer(this.space);

  @override
  Widget build(GroupSetting widget, BuildContext context) {
    return SizedBox(height: space);
  }
}

class _ItemLeading extends Item {
  final String leading;

  _ItemLeading(this.leading);

  @override
  Widget build(GroupSetting widget, BuildContext context) {
    return Padding(
      // symmetric：用于设置组件的垂直、水平间距
      // 属于组合式设置方法的一种
      padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
      // 主要内容就是 Text 了，用于显示标签文本
      // 注意颜色和字体大小
      child: Text(
        leading,
        style: const TextStyle(fontSize: 14),
      ),
    );
  }
}

abstract class _ItemCommon extends Item {
// 图标（接受 Image | Icon 两个种类，不限定具体使用什么）
  final Widget? icon;

// 主标题
  final String title;

// 子标题
  final String? subtitle;

// 描述文本
  final String? description;

// 是否显示右箭头（表示可以跳转下一级操作）
  final bool arrow;

// onTap | goto 二选一
  final VoidCallback? onTap;

// 一般设置项都是仅跳转，所以添加一个快捷方式
  final Type? goto;

  _ItemCommon({
    this.icon,
    required this.title,
    this.subtitle,
    this.description,
    this.arrow = true, // 默认显示这个右箭头，不需要的话设置为 false 就可以了
    this.onTap, // 用于处理点击事件的回调
    this.goto, // 当内容项仅跳转页面时，可以使用此属性设置路由跳转地址
  })  : assert(icon == null || icon is Image || icon is Icon),
        assert(onTap == null || goto == null);

// 这个方法留给子类去实现，具体怎样实现，这里不用关心
  Widget? ending(GroupSetting widget, BuildContext context) => null;

  @override
  Widget build(GroupSetting widget, BuildContext context) {
    // 获取统一主题数据
    // 可以用它来复制默认主题样式
    final theme = Theme.of(context);

    // Row 的子项列表，这样写好处是便于我们在逻辑分支中添加组件
    List<Widget> items = <Widget>[];

    // 构建图标
    // 这里的图标为了不限制死，支持两种写法
    // 一是 Image 图片资源，但是为了防止外部设置图片尺寸，所以这里只使用图片源而固定宽高
    // 二是 Icon 字体图标，这样不仅可以显示字体图片也支持图片
    Widget? imageIcon;
    if (icon != null) {
      if (icon is Image) {
        imageIcon = Image(
          image: (icon as Image).image,
          width: 32,
          height: 32,
        );
      } else if (icon is Icon) {
        imageIcon = IconTheme(
          data: theme.iconTheme.copyWith(size: 18),
          child: icon as Icon,
        );
      }
    }
    // 如果上面对 imageIcon 进行了初始化，那说明此变量不为空
    // 直接将其添加到 items 中即可
    if (imageIcon != null) {
      items.add(Padding(padding: widget.boxInsets, child: imageIcon));
    }


    // 主标题
    // 默认我们认为没有子标题，所以 title 就成了唯一的内容
    // 因此可以直接使用 Text 来实例化 caption 对象
    Widget caption = Text(
      title,
      style: theme.textTheme.bodyLarge?.copyWith( // 使用主题文本样式
        color: theme.colorScheme.onSurface, // 文字颜色与表面背景适配
      ),
    );

    // 子标题
    // 这里当判断子标题不为空（或者空字符串）时
    // 我们将其改变为 Column 上下布局的方式，就可以将子标题显示在 title 下方了
    if (subtitle?.isNotEmpty ?? false) {
      caption = Column(
        mainAxisSize: MainAxisSize.max,
        // 此属性表示在纵向方向上靠左排列
        // CrossAxisAlignment.end 则靠右排列
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          caption,
          Text(
            subtitle!,
            style: const TextStyle(fontSize: 12,),
            strutStyle: const StrutStyle(leading: 0, forceStrutHeight: true),
          )
        ],
      );
    }

    // 这里是为了防止没有传递任何图标，因此缺少一个空位
    // 那么标题组件就会紧挨着左侧，一点间隙都没有
    // 所以当没有图标的时候，给标题栏左侧设置一个间距
    if (imageIcon == null) {
      caption = Padding(
        padding: EdgeInsets.only(left: widget.boxInsets.left),
        child: caption,
      );
    }

    // 这里由于标题栏是真个内容的主体
    // 所以将其使用 Expanded 包裹起来，撑满整个 Row 的剩余空间
    items.add(
        Expanded(child: caption),
    );

    // 描述文本
    if (description?.isNotEmpty ?? false) {
      items.add(Text(
        description!,
        style: theme.textTheme.bodyLarge?.copyWith(
          fontSize: 14,
          color: theme.colorScheme.onSurface.withOpacity(0.6),
        ),
      ));
    }

    // 添加尾部小组件（这个留给具体的子类去实现，公共类中不作处理）
    final endWidget = ending(widget, context);
    if (endWidget != null) {
      items.add(endWidget);
    }

    // 显示右箭头
    if (arrow) {
      items.add(Padding(
        padding: widget.boxInsets.copyWith(left: 0),
        child: const Icon(
          Icons.arrow_forward_ios_sharp,
          size: 18,
        ),
      ));
    }

    // Clickable 一个具有点击效果并且能处理点击事件的自定义组件
    // context.routeTo(goto!)
    return Clickable(
      backgroundColor: theme.colorScheme.surface,
      onTap: goto == null ? onTap : () => context.routeTo(goto!),
      padding: widget.boxInsets,
      // border: Border(
      //   bottom: BorderSide(color: theme.colorScheme.outline) // 使用主题边框色
      // ),
      onLongPress: (Offset offset, BuildContext context) {  },
      child: Row(
        mainAxisSize: MainAxisSize.max,
        children: items,
      ),
    );
  }
}

class _ItemText extends _ItemCommon {
  _ItemText({
    super.icon,
    required super.title,
    super.subtitle,
    super.description,
    super.onTap,
    super.goto,
  });
}

class _ItemSwitcher extends _ItemCommon {
// 状态开关的初始值（ture：打开，false：关闭）
  final bool value;
// 状态切换回调
  final OnChanged? onChanged;

  _ItemSwitcher({
    super.icon,
    required super.title,
    super.subtitle,
    super.description,
    this.value = false,
    this.onChanged,
  }) : super(arrow: false); // arrow 为 false 即不显示右侧箭头

  @override
  Widget? ending(GroupSetting widget, BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(right: widget.boxInsets.right),
      // Switcher 是我基于 flutter_switch 组件进行二次封装的一个组件
      child: Switcher(value: value, onChanged: onChanged),
    );
  }
}

class _ItemNotification extends _ItemCommon {
  _ItemNotification({
    super.icon,
    required super.title,
    super.subtitle,
    super.description,
    super.onTap,
    super.goto,
  });

  @override
  Widget? ending(GroupSetting widget, BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(left: widget.boxInsets.left),
      child: const Badge(
        label: Text(
          "NEW",
        ),
      ),
    );
  }
}

